﻿using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Happy.Domain.EntityFramework.Test.Stub;

namespace Happy.Domain.EntityFramework.Test
{
    [TestClass]
    public class RepositoryTest
    {
        private User _testUser = new User(Guid.NewGuid()) { Name = "段光伟", Age = 28 };

        [TestInitialize]
        public void TestInitialize()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                unitOfWork.Database.ExecuteSqlCommand("DELETE FROM Users");

                repository.Save(_testUser);
                unitOfWork.Flush();
            }
        }

        [TestMethod]
        public void Contains_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                Assert.IsFalse(repository.Contains(_testUser));

                var testUser = repository.Load(_testUser.Id);

                Assert.IsTrue(repository.Contains(testUser));
            }
        }

        [TestMethod]
        public void Save_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                var user = new User(Guid.NewGuid()) { Name = "段光宇", Age = 28 };
                repository.Save(user);

                unitOfWork.Flush();

                var count = unitOfWork
                    .Database
                    .SqlQuery<int>("SELECT COUNT(*) FROM Users")
                    .First();

                Assert.AreEqual(2, count);
            }
        }

        [TestMethod]
        public void Update_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                _testUser.Name = "段光宇";
                repository.Update(_testUser);
                unitOfWork.Flush();

                var count = unitOfWork
                    .Database
                    .SqlQuery<int>("SELECT COUNT(*) FROM Users WHERE Name = {0}", "段光宇")
                    .First();

                Assert.AreEqual(1, count);
            }
        }

        [TestMethod]
        public void Delete_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                repository.Delete(_testUser);
                unitOfWork.Flush();

                var count = unitOfWork
                    .Database
                    .SqlQuery<int>("SELECT COUNT(*) FROM Users")
                    .First();

                Assert.AreEqual(0, count);
            }
        }

        [TestMethod]
        public void Merge_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                _testUser.Name = "段光宇";
                repository.Merge(_testUser);
                unitOfWork.Flush();

                var count = unitOfWork
                    .Database
                    .SqlQuery<int>("SELECT COUNT(*) FROM Users WHERE Name = {0}", "段光宇")
                    .First();

                Assert.AreEqual(1, count);
            }
        }

        [TestMethod]
        public void Evict_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                var testUser = repository.Load(_testUser.Id);

                Assert.IsTrue(repository.Contains(testUser));

                repository.Detach(testUser);

                Assert.IsFalse(repository.Contains(testUser));
            }
        }

        [TestMethod]
        public void Load_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                Assert.IsNotNull(repository.Load(_testUser.Id));
            }
        }

        [TestMethod]
        public void Refresh_Test()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                var repository = unitOfWork.CreateRepository<UserRepository>();

                var testUser = repository.Load(_testUser.Id);

                var count = unitOfWork
                    .Database
                    .ExecuteSqlCommand("UPDATE Users SET Name = {0}", "段光宇");

                repository.Refresh(testUser);
                Assert.AreEqual("段光宇", testUser.Name);
            }
        }

        [TestCleanup]
        public void TestCleanup()
        {
            using (var unitOfWork = new TestUnitOfWork())
            {
                unitOfWork.Database.ExecuteSqlCommand("DELETE FROM Users");
            }
        }
    }
}
